<template>
  <div class="upload-image-container">
    <a-upload
      :custom-request="handleUpload"
      :show-file-list="false"
      :accept="accept"
      :disabled="disabled || loading"
      @change="handleChange"
    >
      <template #upload-button>
        <div
          class="upload-trigger"
          :class="[{ 'has-image': modelValue }, `shape-${shape}`]"
          :style="{
            width: typeof width === 'number' ? `${width}px` : width,
            height: typeof height === 'number' ? `${height}px` : height,
          }"
        >
          <template v-if="modelValue">
            <img :src="modelValue" class="preview-image" :class="`shape-${shape}`" />
            <div class="image-overlay" :class="`shape-${shape}`">
              <div class="overlay-buttons">
                <BaseIcon name="icon-edit" class="action-icon" />
                <BaseIcon name="icon-delete" class="action-icon" @click.stop="handleDelete" />
              </div>
            </div>
          </template>
          <template v-else>
            <div class="upload-placeholder">
              <BaseIcon name="icon-plus" />
              <div class="upload-text">{{ placeholder }}</div>
            </div>
          </template>
        </div>
      </template>
    </a-upload>

    <LoadingSpinner :visible="loading" text="上传中..." />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { uploadService } from '@/services/upload'
import { useNotification } from '@/composables/useNotification'
import LoadingSpinner from '@/components/LoadingSpinner.vue'
import type { FileItem, RequestOption, UploadRequest } from '@arco-design/web-vue'
import BaseIcon from '@/components/BaseIcon.vue'
import '@/assets/styles/components/upload-image.css'

const loading = ref(false)
const notification = useNotification()

const props = defineProps({
  modelValue: {
    type: String,
    default: '',
  },
  accept: {
    type: String,
    default: 'image/*',
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  placeholder: {
    type: String,
    default: '点击上传',
  },
  storageType: {
    type: String,
    default: undefined,
  },
  shape: {
    type: String as () => 'square' | 'circle' | 'rectangle',
    default: 'square',
  },
  width: {
    type: [Number, String],
    default: 100,
  },
  height: {
    type: [Number, String],
    default: 100,
  },
})

const emit = defineEmits(['update:modelValue', 'change'])

const handleUpload = (option: RequestOption): UploadRequest => {
  const uploadRequest: UploadRequest = {
    abort: () => {
      loading.value = false
    },
  }

  const doUpload = async () => {
    try {
      if (!option.fileItem.file) {
        throw new Error('未选择文件')
      }

      loading.value = true
      const imageUrl = await uploadService.uploadImage(option.fileItem.file, props.storageType)

      if (imageUrl) {
        emit('update:modelValue', imageUrl)
        option.onSuccess(imageUrl)
        notification.success('上传成功')
      } else {
        throw new Error('上传失败')
      }
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '上传失败'
      notification.error(errorMessage)
      option.onError(error as Error)
    } finally {
      loading.value = false
    }
  }

  doUpload()
  return uploadRequest
}

const handleChange = (fileList: FileItem[], fileItem: FileItem) => {
  const maxSize = 5 * 1024 * 1024
  if (fileItem.file && fileItem.file.size > maxSize) {
    notification.warning('文件大小不能超过5MB')
    return
  }

  emit('change', fileItem)
}

const handleDelete = (event: Event) => {
  event.preventDefault()
  event.stopPropagation()

  emit('update:modelValue', '')
  notification.success('已删除图片')
}
</script>

<style>
@import '@/assets/styles/components/upload-image.css';
</style>
